<?php

class Storage_Adapter_S3 extends Storage_Adapter
{
	protected $_basePath;

	protected $_baseUrl;

	protected $_key = '';

	protected $_secret = '';

	protected $_bucket = '';

	protected $_region;

	protected $_streamWrapper;

	protected $_s3;

	protected $_region = '';

	protected $_ssl = FALSE;

	protected $_endpoint = 's3.amazonaws.com';

	public function __construct($id, $config)
	{
		$this -> _id = $id;
		$this -> _secret = $config['secret'];
		$this -> _key = $config['key'];
		$this -> _bucket = $config['bucket'];
		$this -> _region = $config['region'];
		$this -> _ssl = $config['ssl'];
		$this -> _endpoint = $config['endpoint'];

		if ($config['baseUrl'])
		{
			$this -> _baseUrl = 'http://' . $this -> _bucket . '.s3.amazonaws.com/';
		}
		else
		{
			$this -> _baseUrl = rtrim($config['baseUrl'], '/') . '/';
		}

		$this -> _basePath = rtrim($this -> _bucket . '/' . $path, '/') . '/';
	}

	function getS3()
	{
		if (null == $this -> _s3)
		{
			require_once dirname(__FILE__) . '/libs/S3.php';
			$this -> _s3 = new S3($this -> _key, $this -> _secret, $this -> _ssl, $this -> _endpoint);
		}
		return $this -> _s3;
	}

	function get($relative_path, $local_file, $force = TRUE)
	{
		self::_makeLocalDir(dirname($local_file));

		$path = $this -> mapPath($relative_path);

		if (!$this -> getS3() -> getObject($this -> _bucket, $path, $local_file))
		{
			if ($force)
			{
				throw new Storage_Exception('could not get {from} to s3 {to}', array(
					'{from}' => $path,
					'{to}' => $local_file
				));
			}
		}

	}

	/**
	 *
	 */
	public function put($relative_path, $local_file, $force = TRUE)
	{

		$path = $this -> mapPath($relative_path);

		if (!$this -> getS3() -> putObjectFile($local_file, $this -> _sBucket, $path, S3::ACL_PUBLIC_READ))
		{
			if ($force)
			{
				throw new Storage_Exception('could not put {from} to s3 {to}', array(
					'{from}' => $local_file,
					'{to}' => $path
				));
			}
			return FALSE;
		}

		return TRUE;
	}

	function getContents($relative_path, $force = TRUE)
	{
		$path = $this -> mapPath($relative_path);

		$data = $this -> getS3() -> getObject($this -> _bucket, $path, FALSE);

		if ($data === FALSE)
		{
			if ($force)
			{
				throw new Storage_Exception('File {file} does not exists!', array('{file}' => $path));
			}
		}
		return $data;
	}

	function putContents($relative_path, $data, $force = TRUE)
	{
		$path = $this -> mapPath($relative_path);

		if (!$this -> getS3() -> putObject($data, $this -> _bucket, $path, S3::ACL_PUBLIC_READ))
		{
			if ($force)
			{
				throw new Storage_Exception('could not put data to s3 {to}', array(
					'{to}' => $path
				));
			}
			return FALSE;
		}

		return TRUE;
	}

	function delete($relative_path, $force = TRUE)
	{
		$path = $this -> mapPath($relative_path);

		if (!$this -> _oObject -> deleteObject($this -> _sBucket, $path))
		{
			if ($force)
			{
				throw new Storage_Exception('File {file} could not be removed!', array('{file}' => $path));
				return FALSE;
			}
		}
		return TRUE;
	}

	function isFile($relative_path)
	{
		return @file_exists($this -> mapPath($relative_path));
	}

	function isDir($relative_path)
	{
		$path = $this -> mapPath($relative_path);
		return is_dir($path);
	}

	function makeDir($relative_path, $mode = 0777)
	{
		$path = $this -> mapPath($relative_path);

		if (is_dir($path))
		{
			return TRUE;
		}

		$path = $this -> mapPath($relative_path);

		$parts = array_filter(explode('/', $path));

		$pPath = array_shift($parts);

		while (count($parts) > 0)
		{
			$pPath .= '/' . array_shift($parts);

			// If it doesn't exist, create it
			if (!is_dir($pPath))
			{
				if (!@mkdir($pPath))
				{
					throw new Storage_Exception('Unable to make directory "{dir}"', array('{dir}' => $pPath));
				}
				@chmod($pPath, $mode);
			}
		}

		if (!is_dir($path))
		{
			throw new Storage_Exception('Unable to make directory "{dir}"', array('dir' => $path));
		}
		return TRUE;

	}

}
